#include "bik_gameworld.h"
//#include "pvu_game_ui.h"
//#include "pvu_game_editor.h"
//#include "pvu_level_select.h"
//#include "pvu_level_complete.h"
//#include "pvu_collision_wall.h"

#include "graphics/graphics_util.h"
#include "input/mouse.h"
#include "input/keyboard.h"
#include "bones/biped_instance.h"
#include "input/mouse.h"
#include "ui/ui_manager.h"
#include "math/intersection.h"
#include "well/base_decoration.h"
#include "script/scripthelper.h"
#include "script/write_lua.h"
#include "font/font_manager.h"
#include "gameflow/game_flow_manager.h"
#include "console/console.h"
#include "dd/dd_man.h"
#include "vfs/vfs.h"


#include "util/mmgr.h"		    // Needs to come in early
#include "util/common_macros.h"		// macros
#include "util/log.h"		    // logging
#include "util/timer.h"		    // logging

#include "num/rand.h"
#include <algorithm>
#include "application/game_application.h"

#include <algorithm>
#include <cassert>
using namespace script;


BIKGameWorld::BIKGameWorld() :
	//m_pEditor(0),
	//m_pUI(0),
	m_RenderDebug(false),
	m_ShowHelp(true),
	m_Scale(1),
	//m_pLevelSelect(NULL),
	//m_pLevelComplete(NULL),
	m_File("")
{
//	m_BG.SetBackgroundTile(10,10,math::Vec2(512*GraphicsUtil::InvW, 512*GraphicsUtil::InvH));
	m_BG.SetBackground("backgrounds/img_levelBG_01_mines.jpg");

	m_Help = "\n\n\n\n\nIngame Help [H]:					\n" 
			"[F1]	Pause and edit user mode		\n" 
			"[F2]	Pause and enter decal editor	\n";
	//m_pWalls = new PVUCollisionWalls(this);
		
}



BIKGameWorld::~BIKGameWorld()
{
	Shutdown();
	ShutdownUI();
	Clear();
	//UTIL_SAFE_DELETE(m_pWalls);
}


void	BIKGameWorld::ShutdownUI()
{
	//UTIL_SAFE_DELETE(m_pUI);

}

void	BIKGameWorld::Shutdown()
{	

}

void	BIKGameWorld::Clear()
{
	//UTIL_SAFE_DELETE(m_pLevelComplete);
	//m_pWalls->Clear();
}


void	BIKGameWorld::Init()
{
}

void	BIKGameWorld::InitUI()
{
	//if(!m_pLevelSelect)
	//	m_pLevelSelect = new PVULevelSelect(this);

	//if(!m_pUI)
	//	m_pUI = new PVUGameUI(this);
}

void	BIKGameWorld::SetScale(float f)
{
	m_Scale = f;
	UTIL_CLAMP(m_Scale, 0.1f, 2.0f);
}

void	BIKGameWorld::Render()
{
	math::Vec2		Offset = GetScrollOffset();
	m_BG.RenderBackground(GetScale());


	if (m_RenderDebug)
	{
		RenderDebug();
	}
	//if (m_pEditor)
	//	m_pEditor->Render();
	


	//std::sort(m_GObjs.m_Objects.begin(), m_GObjs.m_Objects.end(), PVUGObj::SortFunc);
	//for (unsigned int i=0; i<m_GObjs.size(); i++)
	//{
	//	if (m_GObjs[i]->IsVisible(Offset, GetScale()))
	//		m_GObjs[i]->RenderShadow(Offset, GetScale());
	//}
	//m_GObjs.Render(Offset, GetScale());
	m_BG.RenderForeground(GetScale());
}

void		BIKGameWorld::RenderDebug()
{
	if (m_BG.GetEditor()) return;

	dd::Manager& DD = dd::Manager::Instance();
	math::Vec2	Offset = GetScrollOffset();

	//m_pWalls->RenderDebug(Offset, GetScale());
	//m_GObjs.RenderDebug(Offset, GetScale());
	//if (!m_pEditor && m_ShowHelp)
	{
	//	FontManager::Instance().Print(math::Vec2(0,0), m_Help.c_str());

	}
}




void	BIKGameWorld::RenderUI()
{
//	if (m_pUI) m_pUI->Render();
}

void	BIKGameWorld::MouseScroll(float dt)
{
//	if (!m_EnableScroll) return;

	// setup the scrolling
	const	float	ScrollBorderMinX = 0.02f;
	const	float	ScrollBorderMaxX = 1.0f - ScrollBorderMinX ;
	const	float	ScrollBorderMinY = 0.02f;
	const	float	ScrollBorderMaxY = 1.0f - ScrollBorderMinY;
	const	float	ScrollSpeed	 = 0.8f;

	dt = dt / GetScale();	// speed up as it zooms out
	math::Vec2	P = m_BG.GetOffset();
	if (m_FocusPoint.x < ScrollBorderMinX)
	{
		m_BG.SetOffset(math::Vec2(P.x - (ScrollSpeed*dt), P.y));
	}else 
	if (m_FocusPoint.x > ScrollBorderMaxX)
	{
		m_BG.SetOffset(math::Vec2(P.x + (ScrollSpeed*dt), P.y));
	}

	if (m_FocusPoint.y < ScrollBorderMinY)
	{
		m_BG.SetOffset(math::Vec2(P.x, P.y - (ScrollSpeed*dt)));
	}
	else if (m_FocusPoint.y > ScrollBorderMaxY)
	{
		m_BG.SetOffset(math::Vec2(P.x, P.y + (ScrollSpeed*dt)));
	}
}

void	BIKGameWorld::Tick(float dt)
{
	// temp; always scroll for now
	//if (m_pEditor)
	{
		//m_pEditor->Tick(dt);
	//	if (g_pApp->MouseInside())
		{
	//		MouseScroll(dt);
		}
	//	if (m_pEditor->PauseGame())		
	//		return;
	} 
	m_BG.Tick(dt);
	if (m_BG.GetEditor())
	{
		MouseScroll(dt);
		// don't update anythign else
		return;
	}
	//m_GObjs.Tick(dt);
	
	//if(m_pUI)
	//	m_pUI->Tick(dt);
}

void	BIKGameWorld::Save(const std::string& File)
{
	WriteLua	wl;
	if (!wl.Open(File)) return;

	wl.StartTable("BGScene");
		m_BG.SaveFile(wl);
	wl.CloseTable(false);

	//m_pWalls->Save(wl);
}




void	BIKGameWorld::Load(const std::string& File)
{
	if (File.empty()) return;
	
	// what's the simplest way to load you?
	vfs::LoadedBlock Block;
	if (!vfs::VFS::Instance().GetFile(File, Block))
	{
		_LOG(MSG_SCRIPT, "Unable to load script file " << File);
		return;
	} 
	Clear();
	LoadFromMemory(Block);
	m_File = File;
}

void		BIKGameWorld::LoadFromMemory(vfs::LoadedBlock& Block)
{
	
	LuaPlus::LuaState*	pScript = ScriptHelper::CreateLuaState();
	if (!ScriptHelper::DoBlock(*pScript, Block))
	{
		_LOG(MSG_ERROR, "Unable to load room file from " << Block.FileName);
		LuaState::Destroy( pScript );
		return;
	} else
	{
		m_Scale = 1.0f;
		m_BG.DeleteObjects();	// clear all previous backgrounds
		m_BG.LoadFile(*pScript);

		// Load the walls
		//m_pWalls->Clear();
		//m_pWalls->Load(*pScript);

	}
	LuaState::Destroy( pScript );

	InitUI();
	//OnStartEditClick();
}

void		BIKGameWorld::KeyPressed(input::Keyboard::KEY* pKey)
{
	//if (m_pEditor)
	{
	//	m_pEditor->KeyPressed(pKey);
	} 
	//else
	{
		m_BG.KeyPressed(pKey);
		if (m_BG.GetEditor())
		{
			return;
		}

	}

	switch (pKey->KeyID)
	{
		case KEY_F1:		
		//if (m_pEditor)
		{
		//	Save("levels/autosave.lua");
		//	UTIL_SAFE_DELETE(m_pEditor);
		//	Init();
		} 
		//else
		{
		//	m_pEditor = new PVUGameEditor(this);
		//	Shutdown();
		}
		break;
		case KEY_H:
			m_ShowHelp = !m_ShowHelp;
			break;
		case KEY_D:
			m_RenderDebug = !m_RenderDebug;
			break;
		case KEY_T:
			//if (m_pLevelSelect)
			{
			//	if (m_pLevelSelect->IsValid())
			//		m_pLevelSelect->ShutdownUI();
			//	else
			//		m_pLevelSelect->InitUI();
			}
			break;

	}
}

math::Vec2		BIKGameWorld::ScreenToWorld(const math::Vec2& Screen)
{
	return GetScrollOffset() + ( Screen / m_Scale); 
}

void		BIKGameWorld::KeyDown(input::Keyboard::KEY* pKey)
{
	if (m_BG.GetEditor())
	{
		m_BG.KeyDown(pKey);
		return;
	}
	switch (pKey->KeyID)
	{
		case KEY_PLUS:	SetScale(GetScale() + TIMER().Delta()); break;
		case KEY_MINUS:	SetScale(GetScale() - TIMER().Delta()); break;
	}

	//if (m_pEditor) m_pEditor->KeyDown(pKey);


}
void		BIKGameWorld::MouseMove(const math::Vec2& From, const math::Vec2& To)
{
	m_FocusPoint = To;
	if (m_BG.GetEditor())
	{
		m_BG.MouseMove(From, To);
		return;
	}
	//if (m_pEditor)
	{
	//	m_pEditor->MouseMove(From, To);
	} 
	//else
	{
		m_CurrentPos = To + GetScrollOffset();
	}
}
void		BIKGameWorld::MouseButtonPressed(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos)
{
	math::Vec2	P = ScreenToWorld(Pos);

	if(ui::UIManager::Instance().MouseInside(Pos))
		 return;


	if (m_BG.GetEditor())
	{
		m_BG.MouseButtonPressed(pKey, Pos);
		return;
	}
	//if (m_pEditor)	
		//m_pEditor->MouseButtonPressed(pKey, Pos);
	 
	
}

void		BIKGameWorld::MouseButtonReleased(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos)
{
	//if (m_pEditor)
	//	m_pEditor->MouseButtonReleased(pKey, Pos);
	 
	
}

void		BIKGameWorld::MouseButtonDown(input::Mouse::BUTTON_STATE* pKey, const math::Vec2& Pos)
{
	//if (m_pEditor)
	//	m_pEditor->MouseButtonDown(pKey, Pos);
	 	
}

void		BIKGameWorld::MouseOnDrag(const math::Vec2& From, const math::Vec2& To) 
{
	//if (m_pEditor) 
	//	m_pEditor->MouseOnDrag(From, To);

}
void		BIKGameWorld::MouseOnDrop(const math::Vec2& From, const math::Vec2& To) 
{
	//if (m_pEditor) 
	//	m_pEditor->MouseOnDrop(From, To);
}
void		BIKGameWorld::MouseWheelMove(int WheelInfo, const math::Vec2& Pos)
{
	if (m_BG.GetEditor())
	{
		m_BG.MouseWheelMove(WheelInfo, Pos);
		return;
	}
	//if (m_pEditor) 
		//m_pEditor->MouseWheelMove(WheelInfo, Pos);
}


void	BIKGameWorld::LevelComplete()
{
	//if(m_pLevelComplete)
	//	return;
	
	//m_pLevelComplete = new PVULevelComplete(this,"ui/Level_Complete.ui");

}

void	BIKGameWorld::LoadLastEdit()
{
	vfs::LoadedBlock Block;
	if (!vfs::VFS::Instance().GetFile("levels/autosave.lua", Block))
	{
		_LOG(MSG_SCRIPT, "Unable to load script file autosave.lua " );
		return;
	} 
	Clear();
	LoadFromMemory(Block);	
}

